package com.lgcns.andteam2.todaymenu;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

import android.app.AlarmManager;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.widget.Toast;

/**
 * BroadcastReceiver
 */
public class MenuReceiver extends BroadcastReceiver {
    private static final String TAG = MenuReceiver.class.getSimpleName();
    SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    private static Toast mToast = null;

    @Override
    public void onReceive(Context context, Intent intent) {
        
        String action = intent.getAction();
        Log.d(TAG, "onReceive() - action : " + action);
        
        if(Intent.ACTION_BOOT_COMPLETED.equals(action)) {
            // device가 부팅 완료된 경우, 다음번 알람을 설정한다.
            setNextAlarm(context, false);
        } else if(Constants.ACTION_ALARM_SETTING_CHANGED.equals(action)) {
            // 미리 알림 설정이 변경된 경우, 존재하는 알람을 없애고, 다음번 알람을 설정해 준다.
            setNextAlarm(context, true);
        } else if(Constants.ACTION_NOTIFY_NEXT_MENU.equals(action)) {
            // 알람시간이 되어 알람이 BR을 발생한 경우 notification 등록, 기존 알람을 취소, 다음 알람을 설정한다.
            NotificationManager nm = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
            Notification noti = new Notification(R.drawable.icon, context.getString(R.string.alarm_ticker), 
                    System.currentTimeMillis());
            noti.vibrate = new long[] { 800, 200, 200, 300, 200, 300, 800, 200, 200, 300, 200, 300 };
            noti.flags |= Notification.FLAG_AUTO_CANCEL;
            
            Intent startIntent = new Intent(context, IntroActivity.class);
            startIntent.putExtra(Constants.EXTRA_REMOVE_NOTIFICATION, true);
            startIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, startIntent, 0);
            noti.setLatestEventInfo(context, context.getString(R.string.alarm_title), 
                    context.getString(R.string.alarm_content), pendingIntent);
            nm.notify(Constants.NOTI_ID_MENU_ALARM, noti);
            
            setNextAlarm(context, false);
        }
    }

    /**
     * 가장 가까운 미래에 도달하는 메뉴 알람을 지정한다. 이미 존재하는 알람이 있으면 취소한다.
     * @param context
     * @param showToast 알람 지정 토스트 메시지 표시 여부
     */
    private void setNextAlarm(Context context, boolean showToast) {
        Log.d(TAG, "setNextAlarm()");

        AlarmManager am = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
        // 이미 존재하는 알람이 있으면 취소
        am.cancel(PendingIntent.getBroadcast(context, Constants.REQ_MENU_ALARM, new Intent(), 0));

        boolean lunchEnabled = Util.getPreferenceBooleanValue(context, Constants.PREF_LUNCH_ALARM_ENABLED, false);
        boolean dinnerEnabled = Util.getPreferenceBooleanValue(context, Constants.PREF_DINNER_ALARM_ENABLED, false);
        
        if(!lunchEnabled && !dinnerEnabled) {
            return;
        }
 
        Calendar now = Calendar.getInstance();
        now.add(Calendar.SECOND, 1); // 알람 발생 시간과 알람 지정작업을 하는 시점에 약간의 오차(현재 < 현재 알람 발생 시간 인 경우가 발생) 보정
        Calendar nextLunchAlarm = null;
        Calendar nextDinnerAlarm = null;
        
        if(lunchEnabled) {
            String lunchTime = Util.getPreferenceStringValue(context, Constants.PREF_LUNCH_ALARM_TIME, null);
            Date date = Util.convertToDate(lunchTime);
            if(date == null) {
                lunchEnabled = false;
            } else {
                nextLunchAlarm = Calendar.getInstance();
                nextLunchAlarm.setTime(date);
                // 지금보다 과거이면,, 1일 이후로 설정
                if(now.getTimeInMillis() > nextLunchAlarm.getTimeInMillis()) {
                    nextLunchAlarm.add(Calendar.DATE, 1);
                }
            }
        }
        
        if(dinnerEnabled) {
            String dinnerTime = Util.getPreferenceStringValue(context, Constants.PREF_DINNER_ALARM_TIME, null);
            Date date = Util.convertToDate(dinnerTime);
            if(date == null) {
                dinnerEnabled = false;
            } else {
                nextDinnerAlarm = Calendar.getInstance();
                nextDinnerAlarm.setTime(date);
                // 지금보다 과거이면,, 1일 이후로 설정
                if(now.getTimeInMillis() > nextDinnerAlarm.getTimeInMillis()) {
                    nextDinnerAlarm.add(Calendar.DATE, 1);
                }
            }
        }
        
        // 가장 가까운 미래의 알람 시간 구하기
        Calendar nextAlarmTime = null;
        
        if(lunchEnabled && !dinnerEnabled) {
            nextAlarmTime = nextLunchAlarm;
        } else if(!lunchEnabled && dinnerEnabled) {
            nextAlarmTime = nextDinnerAlarm;
        } else if(lunchEnabled && dinnerEnabled) {
            nextAlarmTime = (nextLunchAlarm.compareTo(nextDinnerAlarm) <= 0) ? nextLunchAlarm : nextDinnerAlarm;
        } else {
            // 둘 다 false인 경우임. 알람 설정할 필요 없음.
            return;
        }
        
        // 주말인 경우 다음주 월요일로 보정
        int dayOfWeek = nextAlarmTime.get(Calendar.DAY_OF_WEEK);
        if(dayOfWeek == Calendar.SATURDAY) {
            nextAlarmTime.add(Calendar.DATE, 2);
        } else if(dayOfWeek == Calendar.SUNDAY) {
            nextAlarmTime.add(Calendar.DATE, 1);
        }
        
        // 알림시 호출될 BR 지정
        Intent intent = new Intent(context, MenuReceiver.class);
        intent.setAction(Constants.ACTION_NOTIFY_NEXT_MENU);
        PendingIntent pendingIndent = PendingIntent.getBroadcast(context, Constants.REQ_MENU_ALARM, intent, 0);
        
        Log.d(TAG, "nextAlarmTime : " + df.format(nextAlarmTime.getTime()));
        
        // 새로운 알람 설정
        am.set(AlarmManager.RTC, nextAlarmTime.getTimeInMillis(), pendingIndent);

        if(showToast) {
            popAlarmSetToast(context, nextAlarmTime.getTimeInMillis());
        }
    }

    /**
     * 알람 설정되었다는 Toast 메시지를 표시한다.
     * @param context
     * @param timeInMillis
     */
    private static void popAlarmSetToast(Context context, long timeInMillis) {
        String toastText = formatToast(context, timeInMillis);
        Toast toast = Toast.makeText(context, toastText, Toast.LENGTH_SHORT);
        if(mToast != null) {
            mToast.cancel();
        }
        mToast = toast;
        toast.show();
    }

    /**
     * "지금부터 %1$s %2$s %3$s 후로 메뉴 미리 알림이 설정됩니다" 형식으로 포매팅한다.
     */
    private static String formatToast(Context context, long timeInMillis) {
        long delta = timeInMillis - System.currentTimeMillis();
        long hours = delta / (1000 * 60 * 60);
        long minutes = delta / (1000 * 60) % 60;
        long days = hours / 24;
        hours = hours % 24;

        String daySeq = (days == 0) ? "" : context.getString(R.string.day, Long.toString(days));

        String minSeq = (minutes == 0) ? "" : context.getString(R.string.minute, Long.toString(minutes));

        String hourSeq = (hours == 0) ? "" : context.getString(R.string.hour, Long.toString(hours));

        boolean dispDays = days > 0;
        boolean dispHour = hours > 0;
        boolean dispMinute = minutes > 0;

        int index = (dispDays ? 1 : 0) |
                    (dispHour ? 2 : 0) |
                    (dispMinute ? 4 : 0);

        String[] formats = context.getResources().getStringArray(R.array.alarm_set);
        return String.format(formats[index], daySeq, hourSeq, minSeq);
    }
}
